package org.upo.eps.it.phama.struts.action;

import java.io.PrintWriter;
import java.security.NoSuchAlgorithmException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.hibernate.HibernateException;
import org.upo.eps.it.phama.bean.Direccion;
import org.upo.eps.it.phama.bean.Empleado;
import org.upo.eps.it.phama.dao.EmpleadoDAO;
import org.upo.eps.it.phama.struts.actionform.EmpleadosActionForm;
import org.upo.eps.it.phama.util.Utils;

/**
 *
 * @author grupo 4
 */
public class EmpleadosAction extends Action {

    /**
     * This is the action called from the Struts framework.
     *
     * @param mapping The ActionMapping used to select this instance.
     * @param form The optional ActionForm bean for this request.
     * @param request The HTTP Request we are processing.
     * @param response The HTTP Response we are processing.
     * @throws java.lang.Exception
     * @return
     */
    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        HttpSession session = request.getSession();
        String result = "login";
        /* Los métodos execute de todos los Action efectúan la misma comprobación. Si la sesión
         * guarda un atributo User es porque hay un usuario identificado, por lo que se puede
         * continuar con la ejecución del método. Si no lo hay, se redirige al usuario a la página
         * de logado.
         */
        if (session.getAttribute("user") != null) {
            /* Si hay un usuario logado, se efectúa la acción determinada por el atributo
             * opción del ActionForm asociado.
             */
            EmpleadosActionForm af = (EmpleadosActionForm) form;
            String opcion = af.getOpcion().toLowerCase();
            switch (opcion) {
                case "menu":
                    result = "menu";
                    break;
                case "grabar":
                    crear(af, response.getWriter());
                    break;
                case "buscar":
                    result = buscar(af, response.getWriter());
                    break;
                case "eliminar":
                    result = eliminar(af, response.getWriter());
                    break;
                case "modificar":
                    result = modificar(af, response.getWriter());
                    break;
            }
        }
        return mapping.findForward(result);
    }

    //<editor-fold defaultstate="collapsed" desc="private methods">
    private String buscar(EmpleadosActionForm form, PrintWriter out) {
        /* Basicamente, se efectúa una búsqueda de todos los empleados cuyos datos correspondan a los aportados por
         * el usuario en el formulario de búsqueda. Este resultado es asignado al atributo resultadoBusqueda del
         * ActionForm y después se recorre para construir una cadena JSON que se devolverá al cliente por medio
         * del objeto response.
         * Cualquier excepción también se devolverá de la misma forma.
         */
        String result = "failure";
        form.setResultadoBusqueda(EmpleadoDAO.search(form.getNombre(), form.getApellido1(), form.getApellido2(), form.getCategoria(), form.getUsuario()));
        JSONArray jsonArray = new JSONArray();
        try {
            for (Empleado emp : form.getResultadoBusqueda()) {
                JSONObject json = new JSONObject();
                json.put("id", emp.getIdEmpleado());
                json.put("nombre", emp.getNombre());
                json.put("apellido1", emp.getApellido1());
                json.put("apellido2", emp.getApellido2());
                json.put("idDireccion", emp.getDireccion() != null ? emp.getDireccion().getIdDireccion() : "");
                json.put("direccion", emp.getDireccion() != null ? emp.getDireccion().getDomicilio() : "");
                json.put("poblacion", emp.getDireccion() != null ? emp.getDireccion().getPoblacion() : "");
                json.put("provincia", emp.getDireccion() != null ? emp.getDireccion().getProvincia() : "");
                json.put("cp", emp.getDireccion() != null ? emp.getDireccion().getCp() : "");
                json.put("telefono", emp.getTelefono());
                json.put("correo", emp.getEmail());
                json.put("categoria", emp.getCategoria());
                json.put("usuario", emp.getUsuario());
                json.put("contrasena", emp.getContrasena());
                json.put("idJefe", emp.getJefe() != null ? emp.getJefe().getIdEmpleado() : "-1");
                json.put("jefe", emp.getJefe());
                jsonArray.put(json);
            }
            out.print(jsonArray);
            result = "success";
        } catch (JSONException ex) {
            out.println("<div id='excepcion'>");
            out.println(String.format("<ul><li>Se ha producido el siguiente error: %s</li></ul>", ex.getMessage()));
            out.println("</div>");
        } finally {
            return result;
        }
    }

    private String crear(EmpleadosActionForm form, PrintWriter out) {
        /* Para crear un nuevo empleado primero se crea un objeto de la clase Dirección con todos
         * los atributos obtenidos del ActionForm. Este objeto se referencia desde el nuevo objeto
         * empleado, que finalmente se persiste por medio de la clase EmpleadoDAO.
         */
        String result = "failure";
        try {
            Direccion direccion = new Direccion(form.getDireccion(), form.getPoblacion(), form.getProvincia(), form.getCp());
            Empleado empleado = new Empleado(direccion, form.getNombre(), form.getApellido1(), form.getApellido2(), form.getTelefono(), form.getCorreo(), form.getUsuario(), Utils.getMd5(form.getContrasena()), form.getCategoria());
            if (form.getJefe() > 0) { //Sólo si se ha definido un jefe
                Empleado jefe = new Empleado();
                jefe.setIdEmpleado(form.getJefe());
                empleado.setJefe(jefe);
            }
            EmpleadoDAO.save(empleado);
            form.getMisEmpleados().add(empleado);
            result = "success";
        } catch (HibernateException ex) {
            /* Solo se devuelve una cadena en el response si se ha producido alguna excepción */
            out.println("<div id='excepcion'>");
            out.println(String.format("<ul><li>Se ha producido el siguiente error: %s</li></ul>", ex.getMessage()));
            out.println("</div>");
        } catch (NoSuchAlgorithmException ex) {
            out.println("<div id='excepcion'>");
            out.println(String.format("<ul><li>Se ha producido el siguiente error: %s</li></ul>", ex.getMessage()));
            out.println("</div>");
        } finally {
            return result;
        }
    }

    private String eliminar(EmpleadosActionForm form, PrintWriter out) {
        String result = "failure";
        try {
            EmpleadoDAO.delete(form.getId());
            result = "success";
        } catch (HibernateException ex) {
            out.println("<div id='excepcion'>");
            out.println(String.format("<ul><li>Se ha producido el siguiente error: %s</li></ul>", ex.getCause()));
            out.println("</div>");
        } finally {
            return result;
        }
    }

    private String modificar(EmpleadosActionForm form, PrintWriter out) {
        /* Para modificar se procede de forma similar a la creación, con la salvedad de que ahora es necesario
         * asignar el empleado el id que tenemos en el atributo correspondiente del ActionForm. De otra manera, 
         * se tomaría al empleado por uno nuevo y se volvería a crear en la base de datos.
         */
        String result = "failure";
        try {
            Direccion direccion = new Direccion(form.getDireccion(), form.getPoblacion(), form.getProvincia(), form.getCp());
            direccion.setIdDireccion(form.getIdDireccion());
            Empleado empleado = new Empleado(direccion, form.getNombre(), form.getApellido1(), form.getApellido2(), form.getTelefono(), form.getCorreo(), form.getUsuario(), Utils.getMd5(form.getContrasena()), form.getCategoria());
            empleado.setIdEmpleado(form.getId());
            if (form.getJefe() > 0) { //Sólo si se ha definido un jefe
                Empleado jefe = new Empleado();
                jefe.setIdEmpleado(form.getJefe());
                empleado.setJefe(jefe);
            }
            EmpleadoDAO.save(empleado);
            form.getMisEmpleados().add(empleado);
            result = "success";
        } catch (HibernateException ex) {
            out.println("<div id='excepcion'>");
            out.println(String.format("<ul><li>Se ha producido el siguiente error: %s</li></ul>", ex.getMessage()));
            out.println("</div>");
        } catch (NoSuchAlgorithmException ex) {
            out.println("<div id='excepcion'>");
            out.println(String.format("<ul><li>Se ha producido el siguiente error: %s</li></ul>", ex.getMessage()));
            out.println("</div>");
        } finally {
            return result;
        }
    }
    //</editor-fold>
}
